import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class TCPServer {
    private ServerSocket serverSocket=null;
    //指定端口
    public TCPServer(int port) throws IOException {
        serverSocket=new ServerSocket(port);
    }
    //建立连接
    public void start() throws IOException {
        System.out.println("启动服务器");

        ExecutorService threadPool = Executors.newCachedThreadPool();
        while (true){
            Socket clientSocket = serverSocket.accept();
        }


        threadPool.submit(() -> {
            processConnection();
        });
    }
    //处理连接

    private void processConnection(Socket clientSocket) {
        System.out.printf("[%s:%d] 客户端上线!\n", clientSocket.getInetAddress().toString(), clientSocket.getPort());
        try (InputStream inputStream = clientSocket.getInputStream();
             OutputStream outputStream = clientSocket.getOutputStream()) {
            while (true) {
                // 1. 读取请求
                Scanner scanner = new Scanner(inputStream);
                if (!scanner.hasNext()) {
                    // 没有下个数据, 说明读完了. (客户端关闭了连接)
                    System.out.printf("[%s:%d] 客户端下线! \n", clientSocket.getInetAddress().toString(), clientSocket.getPort());
                    break;
                }
                // 注意!! 此处使用 next 是一直读取到换行符/空格/其他空白符结束, 但是最终返回结果里不包含上述 空白符 .
                String request = scanner.next();
                // 2. 根据请求构造响应
                String response = process(request);
                // 3. 返回响应结果.
                //    OutputStream 没有 write String 这样的功能. 可以把 String 里的字节数组拿出来, 进行写入;
                //    也可以用字符流来转换一下.
                PrintWriter printWriter = new PrintWriter(outputStream);
                // 此处使用 println 来写入. 让结果中带有一个 \n 换行. 方便对端来接收解析.
                printWriter.println(response);
                // flush 用来刷新缓冲区, 保证当前写入的数据, 雀食是发送出去了.
                printWriter.flush();

                System.out.printf("[%s:%d] req: %s; resp: %s \n", clientSocket.getInetAddress().toString(), clientSocket.getPort(),
                        request, response);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 更合适的做法, 是把 close 放到 finally 里面, 保证一定能够执行到!!
            try {
                clientSocket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }
    public String process(String request) {
        return request;
    }
    public static void main(String[] args) {

    }
}
